﻿using System;
using PropertyExpression.Common;
using PropertyExpression.ControllableQuery;

namespace ConsoleApplication1
{
    internal class Program
    {
        private static void Main()
        {
            Console.Write("BillOfMaterialsHeaderId=");
            var billOfMaterialsHeaderId = Console.ReadLine();
            Console.Write("ModelPublicationId=");
            var modelPublicationId = Console.ReadLine();
            Console.Write("ServicePartsPageId=");
            var servicePartsPageId = Console.ReadLine();
            Console.Write("RedCondition=");
            var redCondition = bool.Parse(Console.ReadLine());

            foreach (var record in QExecutor.MaterializeReader(
                command => new {
                                   BillOfMaterialsHeaderId = command.Param(() => int.Parse(billOfMaterialsHeaderId)),
                                   ModelPublicationId = command.Param(() => int.Parse(modelPublicationId)),
                                   ServicePartsPageId = command.Param(() => int.Parse(servicePartsPageId)),
                                   redCondition,
                                   redOn = Func.Invoke(
                                       () => {
                                           if (redCondition)
                                           {
                                               Console.Write("LanguageCode=");
                                               var languageCode = Console.ReadLine();
                                               Console.Write("ModelId=");
                                               var modelId = Console.ReadLine();
                                               Console.Write("BlueCondition=");
                                               var blueCondition = bool.Parse(Console.ReadLine());
                                               return new {
                                                              languageCode = command.Param(languageCode),
                                                              modelId = command.Param(() => int.Parse(modelId)),
                                                              blueCondition
                                                          }.AsOption();
                                           }
                                           else
                                               return new {
                                                              languageCode = default(IParam<string>),
                                                              modelId = default(IParam<int>),
                                                              blueCondition = default(bool)
                                                          }.Nothing();
                                       })
                               },
                p => {
                    var q = new Q(@"
FROM    BillOfMaterialsLine
WHERE   BillOfMaterialsHeaderId = ")._(p.BillOfMaterialsHeaderId)._(@"
        AND ( ( BillOfMaterialsLine.MainLinkExcludedFrom = 0
                AND EXISTS ( SELECT 1
                             FROM   MainPartLink
                             WHERE  MainPartLink.PartNumber = BillOfMaterialsLine.PartNumber
                                    AND MainPartLink.ModelPublicationId = ")._(p.ModelPublicationId)._(@"
                                    AND MainPartLink.ServicePartsPageId <> ")._(p.ServicePartsPageId)._(@" )
              )");
                    p.redOn.Some(
                        @on => {
                            q._(@"
              OR ( BillOfMaterialsLine.InnerLinkExcludedFrom = 0
                   AND EXISTS ( SELECT  1
                                FROM    InnerPartLink
                                        INNER JOIN Model
                                            ON InnerPartLink.ModelCode = Model.ModelCode
                                               AND InnerPartLink.ModelSequence = Model.ModelSequence");
                            if (on.blueCondition)
                                q._(@"
                                        INNER JOIN Publication
                                            ON InnerPartLink.PublicationId = Publication.PublicationId");
                            q._(@"
                                        INNER JOIN LocalizedPublication
                                            ON InnerPartLink.PublicationId = LocalizedPublication.PublicationId
                                               AND LocalizedPublication.LanguageCode = ")._(on.languageCode)._(@"
                                WHERE   InnerPartLink.PartNumber = BillOfMaterialsLine.PartNumber
                                        AND Model.ModelId = ")._(on.modelId);
                            if (on.blueCondition)
                                q._(@"
                                        AND Publication.FollowingPublicationId IS NULL");
                            q._(@" )
                 )");
                        });
                    return q._(@"
            )").Select(
                        _ => new {
                                     BillOfMaterialsLineId = _._<int>(),
                                     PartNumber = _._<string>()
                                 });
                }))
                Console.WriteLine("BillOfMaterialsLineId = {0}, PartNumber = {1}",
                    record.BillOfMaterialsLineId,
                    record.PartNumber);
        }
    }
}